// formats_txn.cpp
// Customizer_Base
// Protea Customizer/Customizer Pro / Business Logic for managing formats (buffers)
// Copyright (C) 2003, 2004, 2005 eXegeSys, Inc.
// Copyright (C) 2008 Bruce A. James
//
// This program is part of the Protea Project.
//
// The Protea Project is free software; you can redistribute it and/or modify it 
// under the terms of the GNU General Public License as published by the 
// Free Software Foundation, either version 3 of the License, or (at your 
// option) any later version.
//
// The Protea Project is distributed in the hope that it will be useful, but 
// WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
// or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 
// for more details.
// 
// You should have received a copy of the GNU General Public License along 
// with this program.  If not, see <http://www.gnu.org/licenses/>.
//
// Please send correspondence to:
//
// theproteaproject@gmail.com
//

#include "base_setup.h"

//////////////////////////////////////////////////////////
//
// Transaction code
//
//////////////////////////////////////////////////////////


//@ CHA GetFormatInfo
//@ COD GetFormatInfo
//@ NUM 190
//@ CRI FORMAT_NAME
//@ GEN Used by RevFormat and PrintFormat
//
void GetFormatInfo( XCBuffer* TransBuf, XCTransactionVars* vars ) {
	XCBuffer* dd = NULL;
	XCField* temp;

	XCField* fmt_number = TransBuf->GetField( FLD_FORMAT_NUMBER );
	if (fmt_number && !fmt_number->IsBlank() && fmt_number->GetLong(true) != 0) {
		//@ SUB FormatDescRetrieve Verify the we do have a format with this number
		//@ ERR E (DOESNT_EXIST) Format doesn't exist
		if (!FormatDescRetrieve( TransBuf, vars ))
			vars->Errors->Add( ERR_DOESNT_EXIST, SEV_CRITICAL, FLD_FORMAT_NUMBER, 1, ERR_FORMAT );
	} else {
		// We need to retrieve by name
		FormatDescVerify( TransBuf, VERIFY_REVIEW, vars, false );
	};
	vars->Errors->Check();

	if (IsDatabaseBuffer( TransBuf )) {
		temp = vars->buffer->GetField( FLD_DATABASE_NAME );
		if (temp) {
			//@ GRS
			//@ Check for a DATASET_DESCR record
			dd = vars->myapp->CreateBuffer( FMT_DATASET_DESCR, false );
			try {
				dd->MoveCorresponding( TransBuf, vars->Errors );

				//@ If we have a record, then find the database name
				if (DatasetDescrRetrieve( dd, vars )) {
					//@ GRS
					//@ SUB LookupNumberFromName Change DATABASE_NBR into DATABASE_NAME
					LookupNameFromNumber( vars, dd, vars->buffer, FLD_DATABASE_NBR, FLD_DATABASE_NAME, FMT_DATABASE_DEFN );
					//@ GRE
				};
			} catch( ... ) {
				dd->Release();
				throw;
			};
			dd->Release();

			//@ GRE
		};
	};

	//@ Return child format name
	temp = vars->buffer->GetField( FLD_CHILD_NAME );
	if (temp && TransBuf->GetField( FLD_CHILD_FORMAT )->GetLong( true ) > 0) {
		//@ GRS
		//@ SUB LookupNumberFromName Change CHILD_FORMAT into CHILD_NAME
		LookupNameFromNumber( vars, TransBuf, vars->buffer, FLD_CHILD_FORMAT, FLD_CHILD_NAME, FMT_FORMAT_DESCRIPTR, FLD_FORMAT_NUMBER, FLD_FORMAT_NAME );
		//@ GRE
	};
};




//
//@ CHA RevFormat
//@ COD RevFormat
//@ NUM 190
//@ CRI FORMAT_NAME
//@ CRI APPL_NBR
//@ TAB FORMAT_DESCRIPTR Read
//
//@ GEN RevFormat will review FORMAT_DESCRIPTR records
//
TRANSACTION_CODE( RevFormat ) {
	XCBuffer* TransBuf = NULL;

	//@ GRS Start the transaction
	START_TXN( RevFormat );

		TransBuf = App->CreateBuffer( FMT_FORMAT_DESCRIPTR, false );
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

		START_DB_TXN();
			GetFormatInfo( TransBuf, &txnvars );
		END_DB_TXN();

		//@ Send back result buffer
		txnvars.buffer->MoveCorresponding( TransBuf, txnvars.Errors );
		App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

	CLEANUP_TXN();
		App->CleanupObjects( 1, &TransBuf );
	END_TXN();
	//@ GRE End the transaction
};



//
//@ CHA RevFormats
//@ COD RevFormats
//@ NUM 190
//@ CRI APPL_NBR
//@ TAB FORMAT_DESCRIPTR Read
//
//@ GEN RevFormats returns a list of currently available formats
//
TRANSACTION_CODE( RevFormats ) {
	XCBuffer* TransBuf = NULL;
	XCBuffer* detail = NULL;
	XCBuffer* countbuf = NULL;
	XCDBStatement* stmt = NULL;
	XCField* start = NULL;
	XCField* finish = NULL;
	XCField* partial = NULL;
	bool count_only = false;

	//@ GRS Start the transaction
	START_TXN( RevFormats );
		XCSQLGen* query = txnvars.query;

		//@ Create format descriptor buffer
		TransBuf = App->CreateBuffer( FMT_FORMAT_DESCRIPTR, false );

		//@ Move screen info to transaction buffer
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

//		TransBuf->Validate();

		//@ Start the database transaction
		START_DB_TXN();

			XCField* list[7];
			XCCompare comptemp[6];
			XCOrder order;
			int fcount = 0;

			//@ SUB ValidateAppNumber ensure that we have a valid application number
			ValidateAppNumber( &txnvars );
			TransBuf->DebugDump();

			// Select on Application number
			XCField* temp = TransBuf->GetField( FLD_APPL_NBR );
			list[ fcount++ ] = temp;

			// Search criteria
			temp = txnvars.buffer->GetField( FLD_START_STRING );
			if (temp && !temp->IsBlank()) {
				start = TransBuf->GetField( FLD_FORMAT_NAME )->Clone();
				start->MoveField( temp );
				list[ fcount ] = start;
				comptemp[ fcount++ ].comparison = cmp_greaterthanequals;
			};
			temp = txnvars.buffer->GetField( FLD_FINISH_STRING );
			if (temp && !temp->IsBlank()) {
				finish = TransBuf->GetField( FLD_FORMAT_NAME )->Clone();
				finish->MoveField( temp );
				list[ fcount ] = finish;
				comptemp[ fcount++ ].comparison = cmp_lessthanequals;
			};
			temp = txnvars.buffer->GetField( FLD_PARTIAL_STRING );
			if (temp && !temp->IsBlank()) {
				partial = TransBuf->GetField( FLD_FORMAT_NAME )->Clone();
				partial->MoveField( temp );
				list[ fcount ] = partial;

				// Is this a partial search, or an exact field?
				if (strchr( temp->GetStringPtr(), '%' ))
					comptemp[ fcount ].comparison = cmp_like;
				fcount++;
			};
			temp = txnvars.buffer->GetField( FLD_FORMAT_TYPE );
			if (temp && !temp->IsBlank())
				list[ fcount++ ] = TransBuf->GetField( FLD_FORMAT_TYPE );

			list[ fcount ] = NULL;

			// Determine if we are doing a count only
			temp = txnvars.buffer->GetField( FLD_RESULT_COUNT );
			if (temp && temp->GetLong( true ) == 1)
				count_only = true;

			// Create the SQL statement
			if (count_only) {
				countbuf = query->MakeCOUNT( TransBuf );
			} else {
				query->MakeSELECT( TransBuf );
			};
			query->AddWHERE( list, comptemp );

			// Only order data when actually grabbing results
			if (!count_only)
				query->AddORDERBY( FLD_FORMAT_NAME, &order );

			// Get the data
			if (count_only) {
				stmt = txnvars.dbtxn->ExecuteSQL( query );

				temp->MoveField( countbuf->GetFieldByIndex(0) );
				App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );
			} else {
				App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

				int child = txnvars.buffer->GetChildFormat();
				if (child) {
					detail = App->CreateBuffer( child, true );

					// Execute the query
					stmt = txnvars.dbtxn->ExecuteSQL( query );

					while (!stmt->Eof()) {
						detail->MoveCorresponding( TransBuf, txnvars.Errors, true );
						App->TransResponse( txnvars.result, detail, TRANS_DETAIL_TYPE );
						stmt->MoveNext();
					};
				};
			};
		END_DB_TXN();

	CLEANUP_TXN();
		App->CleanupObjects( 7, &TransBuf, &stmt, &detail, &countbuf, &start, &finish, &partial );
	END_TXN();
	//@ GRE End the transaction
};



//
//@ CHA RevFormatsComponent
//@ COD RevFormatsComponent
//@ NUM 190
//@ CRI APPL_NBR
//@ TAB FORMAT_DESCRIPTR Read
//
//@ GEN RevFormatsComponent returns a list of currently available formats for a component
//
TRANSACTION_CODE( RevFormatsComponent ) 
{
	XCBuffer* TransBuf = NULL;
	XCBuffer* detail = NULL;
	XCBuffer* countbuf = NULL;
	XCDBStatement* stmt = NULL;
	XCField* start = NULL;
	XCField* finish = NULL;
	XCField* partial = NULL;
	bool count_only = false;

	//@ GRS Start the transaction
	START_TXN( RevFormatsComponent );
		XCSQLGen* query = txnvars.query;

		//@ Create format descriptor buffer
		TransBuf = App->CreateBuffer( FMT_FORMAT_DESCRIPTR, false );

		//@ Move screen info to transaction buffer
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

//		TransBuf->Validate();

		//@ Start the database transaction
		START_DB_TXN();

			XCField* list[7];
			XCCompare comptemp[6];
			XCOrder order;
			int fcount = 0;

			//@ SUB ValidateAppNumber ensure that we have a valid application number
			ValidateAppNumber( &txnvars );
			TransBuf->DebugDump();

			// Select on Application number
			XCField* temp = TransBuf->GetField( FLD_APPL_NBR );
			list[ fcount++ ] = temp;

			// Select on Component id
			XCField* comp_id = TransBuf->GetField( FLD_COMPONENT_ID );
			list[ fcount++ ] = comp_id;

			// Select on Buffer type
			XCField* buf_type = TransBuf->GetField( FLD_FORMAT_TYPE );
			list[ fcount++ ] = buf_type;

			list[ fcount ] = NULL;

			// Determine if we are doing a count only
			temp = txnvars.buffer->GetField( FLD_RESULT_COUNT );
			if (temp && temp->GetLong( true ) == 1)
				count_only = true;

			// Create the SQL statement
			if (count_only) {
				countbuf = query->MakeCOUNT( TransBuf );
			} else {
				query->MakeSELECT( TransBuf );
			};
			query->AddWHERE( list, comptemp );

			// Only order data when actually grabbing results
			if (!count_only)
				query->AddORDERBY( FLD_FORMAT_NAME, &order );

			// Get the data
			if (count_only) {
				stmt = txnvars.dbtxn->ExecuteSQL( query );

				temp->MoveField( countbuf->GetFieldByIndex(0) );
				App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );
			} else {
				App->TransResponse( txnvars.result, txnvars.buffer, TRANS_HEADER_TYPE );

				int child = txnvars.buffer->GetChildFormat();
				if (child) {
					detail = App->CreateBuffer( child, true );

					// Execute the query
					stmt = txnvars.dbtxn->ExecuteSQL( query );

					while (!stmt->Eof()) {
						detail->MoveCorresponding( TransBuf, txnvars.Errors, true );
						App->TransResponse( txnvars.result, detail, TRANS_DETAIL_TYPE );
						stmt->MoveNext();
					};
				};
			};
		END_DB_TXN();

	CLEANUP_TXN();
		App->CleanupObjects( 7, &TransBuf, &stmt, &detail, &countbuf, &start, &finish, &partial );
	END_TXN();
	//@ GRE End the transaction
};




//
//@ CHA PrintFormat
//@ COD PrintFormat
//@ NUM 190
//@ CRI FORMAT_NAME
//@ CRI APPL_NBR
//@ TAB FORMAT_DESCRIPTR Read
//
//@ GEN RevFormat will review FORMAT_DESCRIPTR records
//
TRANSACTION_CODE( PrintFormat ) {
	XCBuffer* TransBuf = NULL;
	XCBuffer* ds = NULL;
	XCBuffer* relate = NULL;
	XCBuffer* detail = NULL;
	XCDBStatement* stmt = NULL;

	XCField* temp;
	XCPrintOutput print( transaction->GetOwner() );

	//@ GRS Start the transaction
	START_TXN( PrintFormat );

		TransBuf = App->CreateBuffer( FMT_FORMAT_DESCRIPTR, false );
		TransBuf->MoveCorresponding( txnvars.buffer, txnvars.Errors );

		ds = App->CreateBuffer( FMT_DATA_STRUCTURES, false );
		relate = App->CreateBuffer( FMT_DB_RELATE, false );

		START_DB_TXN();

			//@ SUB GetFormatInfo to obtain format information
			GetFormatInfo( TransBuf, &txnvars );

			//@ Move information from FORMAT_DESCRIPTR buffer to the DATA_STRUCTURES buffer
			ds->MoveCorresponding( TransBuf, txnvars.Errors );

			//@ Move information from FORMAT_DESCRIPTR buffer to the DB_RELATE buffer
			relate->MoveCorresponding( TransBuf, txnvars.Errors );

			print.Start( UE_PRINTFORMAT );
			print.StartTag( "Report" );
			print.StartTag( "Format" );
			print.OutputBuffer( TransBuf );
			if ((temp = TransBuf->GetField( FLD_DATABASE_NAME )))
				print.OutputField( temp );
			if ((temp = TransBuf->GetField( FLD_CHILD_NAME )))
				print.OutputField( temp );

			//@ SUB DataStructureReviewFormat Check if DATA_STRUCTURES record exists
			stmt = DataStructureReviewFormat( ds, &txnvars );
			detail = App->CreateBuffer(33);

			print.StartTag( "Fields" );
			while (!stmt->Eof()) {
				print.StartTag( "Field" );
				detail->MoveCorresponding( ds, txnvars.Errors );
				LookupNameFromNumber( &txnvars, ds, detail, FLD_FIELD_NUMBER, FLD_FIELD_NAME, FMT_FIELD_DESCRIPTOR );
				print.OutputBuffer( detail );
				print.EndTag();
				stmt->MoveNext();
			};
			App->CleanupObjects( 1, &stmt );
			print.EndTag();

			//@ SUB DBRelateReviewFormat Check for DB_RELATE records
			stmt = DBRelateReviewFormat( relate, &txnvars );

			print.StartTag( "Keys" );
			while (!stmt->Eof()) {
				print.StartTag( "Key" );
				print.OutputBuffer( relate );
				print.EndTag();
				stmt->MoveNext();
			};
			print.EndTag();

			print.Finish();
		END_DB_TXN();

	CLEANUP_TXN();
		App->CleanupObjects( 5, &TransBuf, &ds, &stmt, &relate, &detail );
	END_TXN();
	//@ GRE End the transaction
};
